#pragma once

#include <iostream>
#include <cstring>
#include <cerrno>
#include <sys/epoll.h>
#include "Log.hpp"
#include "Err.hpp"

namespace Yohifo
{
    static const int gsize = 128;   //epoll 的大小
    static const int gepfd = -1;

    enum
    {
        READ = EPOLLIN,
        WRITE = EPOLLOUT,
        ERROR = EPOLLERR
    };

    class Epoller
    {
    public:
        Epoller()
            :epfd_(gepfd)
        {}

        ~Epoller()
        {}

        void Create(int size = gsize)
        {
            epfd_ = epoll_create(size);
            if(epfd_ == -1)
            {
                logMessage(Fatal, "Create epfd fail %d %s", errno, strerror(errno));
                exit(EPOLLCREATE_ERR);
            }

        }

        //根据 fd 和 事件 进行注册
        bool Add(int fd, uint32_t event)
        {
            struct epoll_event ev;  //注册对应的结构体信息
            ev.events = event;
            ev.data.fd = fd;

            int ret = epoll_ctl(epfd_, EPOLL_CTL_ADD, fd, &ev);
            if(ret == -1)
                logMessage(Warning, "Add event fail %d %s", errno, strerror(errno));
            
            return ret == 0;
        }

        bool Del(int fd)
        {
            return (epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, nullptr)) == 0;
        }

        int Wait(struct epoll_event *pev, int num, int timeout)
        {
            return epoll_wait(epfd_, pev, num, timeout);
        }

        int Epfd()
        {
            return epfd_;
        }

        void Close()
        {
            if(epfd_ != gepfd)
            {
                close(epfd_);
            }
        }

    private:
        int epfd_;
    };
}